/*
*   Abricotine - Markdown Editor
*   Copyright (c) 2015 Thomas Brouard
*   Licensed under GNU-GPLv3 <http://www.gnu.org/licenses/gpl.html>
*
*   鸿蒙平台日志工具 - 将console输出写入文件以便调试
*   优化版本：异步写入、日志缓冲、级别过滤
*/

var fs = require("fs"),
    pathModule = require("path"),
    app = require("electron").app,
    constants = require.main.require("./constants.js");

var logDir = pathModule.join(constants.path.userData, "/logs"),
    logFile = pathModule.join(logDir, "app.log"),
    maxLogSize = 5 * 1024 * 1024, // 5MB
    logBuffer = [],
    bufferSize = 0,
    maxBufferSize = 64 * 1024, // 64KB缓冲
    flushInterval = 5000, // 5秒刷新一次
    logDirChecked = false,
    logLevel = process.env.LOG_LEVEL || "INFO", // DEBUG, INFO, WARN, ERROR
    levelPriority = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, LOG: 1 };

// 日志级别检查
function shouldLog(level) {
    var currentPriority = levelPriority[logLevel] || 1;
    var msgPriority = levelPriority[level] || 1;
    return msgPriority >= currentPriority;
}

// 确保日志目录存在（只检查一次）
function ensureLogDir() {
    if (logDirChecked) return;
    try {
        if (!fs.existsSync(logDir)) {
            fs.mkdirSync(logDir, { recursive: true });
        }
        logDirChecked = true;
    } catch (e) {
        // 如果无法创建目录，忽略错误
    }
}

// 检查并轮转日志文件
function rotateLogIfNeeded() {
    try {
        if (fs.existsSync(logFile)) {
            var stats = fs.statSync(logFile);
            if (stats.size > maxLogSize) {
                var oldLogFile = logFile + ".old";
                if (fs.existsSync(oldLogFile)) {
                    fs.unlinkSync(oldLogFile);
                }
                fs.renameSync(logFile, oldLogFile);
            }
        }
    } catch (e) {
        // 忽略轮转错误
    }
}

// 刷新日志缓冲区（异步写入）
function flushLogBuffer() {
    if (logBuffer.length === 0) return;
    
    var logsToWrite = logBuffer.join("");
    logBuffer = [];
    bufferSize = 0;
    
    ensureLogDir();
    rotateLogIfNeeded();
    
    fs.appendFile(logFile, logsToWrite, "utf8", function(err) {
        if (err) {
            // 如果异步写入失败，尝试同步写入（作为后备）
            try {
                fs.appendFileSync(logFile, logsToWrite, "utf8");
            } catch (e) {
                // 如果都失败，尝试输出到stderr
                try {
                    process.stderr.write("[LOG ERROR] Failed to write logs: " + e.message + "\n");
                } catch (e2) {
                    // 忽略
                }
            }
        }
    });
}

// 写入日志（优化版本：使用缓冲和异步）
function writeLog(level, message, source) {
    if (!shouldLog(level)) return;
    
    try {
        var timestamp = new Date().toISOString();
        var logEntry = "[" + timestamp + "] [" + level + "]";
        if (source) {
            logEntry += " [" + source + "]";
        }
        logEntry += " " + message + "\n";
        
        // 添加到缓冲区
        logBuffer.push(logEntry);
        bufferSize += Buffer.byteLength(logEntry, "utf8");
        
        // 如果缓冲区太大，立即刷新
        if (bufferSize >= maxBufferSize) {
            flushLogBuffer();
        }
    } catch (e) {
        // 如果格式化失败，尝试输出到stderr
        try {
            process.stderr.write("[LOG ERROR] " + e.message + "\n");
        } catch (e2) {
            // 忽略
        }
    }
}

// 定期刷新日志缓冲区
setInterval(flushLogBuffer, flushInterval);

// 应用退出时刷新所有日志
if (typeof process !== "undefined" && process.on) {
    process.on("exit", function() {
        flushLogBuffer();
    });
    
    // 处理未捕获的异常
    process.on("uncaughtException", function(err) {
        writeLog("ERROR", "Uncaught Exception: " + (err.message || String(err)) + "\n" + (err.stack || ""), "Process");
        flushLogBuffer();
    });
}

// 格式化消息
function formatMessage(args) {
    if (args.length === 0) return "";
    if (args.length === 1) {
        if (typeof args[0] === "object") {
            try {
                return JSON.stringify(args[0], null, 2);
            } catch (e) {
                return String(args[0]);
            }
        }
        return String(args[0]);
    }
    return args.map(function(arg) {
        if (typeof arg === "object") {
            try {
                return JSON.stringify(arg);
            } catch (e) {
                return String(arg);
            }
        }
        return String(arg);
    }).join(" ");
}

var Logger = {
    log: function() {
        var message = formatMessage(Array.prototype.slice.call(arguments));
        writeLog("LOG", message);
        // 同时尝试输出到stdout（如果可用）
        try {
            process.stdout.write("[LOG] " + message + "\n");
        } catch (e) {
            // 忽略
        }
    },
    
    info: function() {
        var message = formatMessage(Array.prototype.slice.call(arguments));
        writeLog("INFO", message);
        try {
            process.stdout.write("[INFO] " + message + "\n");
        } catch (e) {
            // 忽略
        }
    },
    
    warn: function() {
        var message = formatMessage(Array.prototype.slice.call(arguments));
        writeLog("WARN", message);
        try {
            process.stderr.write("[WARN] " + message + "\n");
        } catch (e) {
            // 忽略
        }
    },
    
    error: function() {
        var message = formatMessage(Array.prototype.slice.call(arguments));
        writeLog("ERROR", message);
        try {
            process.stderr.write("[ERROR] " + message + "\n");
        } catch (e) {
            // 忽略
        }
    },
    
    debug: function() {
        var message = formatMessage(Array.prototype.slice.call(arguments));
        writeLog("DEBUG", message);
        try {
            process.stdout.write("[DEBUG] " + message + "\n");
        } catch (e) {
            // 忽略
        }
    },
    
    // 从webContents的console-message事件记录日志
    logConsoleMessage: function(level, message, line, sourceId) {
        var levelMap = {
            0: "LOG",
            1: "WARN", 
            2: "ERROR",
            3: "INFO",
            4: "DEBUG"
        };
        var logLevel = levelMap[level] || "LOG";
        var source = sourceId ? pathModule.basename(sourceId) : "unknown";
        var fullMessage = message + " (Line " + line + " in " + source + ")";
        writeLog(logLevel, fullMessage, "Renderer");
        try {
            process.stdout.write("[" + logLevel + "] [Renderer] " + fullMessage + "\n");
        } catch (e) {
            // 忽略
        }
    },
    
    // 获取日志文件路径
    getLogPath: function() {
        return logFile;
    },
    
    // 设置日志级别
    setLevel: function(level) {
        if (levelPriority.hasOwnProperty(level)) {
            logLevel = level;
        }
    },
    
    // 获取当前日志级别
    getLevel: function() {
        return logLevel;
    },
    
    // 立即刷新日志缓冲区
    flush: function() {
        flushLogBuffer();
    }
};

module.exports = Logger;

